package com.xh.hongaicodegenerator.langgraph4j.node;

import com.xh.hongaicodegenerator.constant.AppConstant;
import com.xh.hongaicodegenerator.langgraph4j.model.enums.TemplateTypeEnum;
import com.xh.hongaicodegenerator.langgraph4j.state.WorkflowContext;
import com.xh.hongaicodegenerator.langgraph4j.tools.CodeFileReaderTool;
import com.xh.hongaicodegenerator.model.enums.CodeGenTypeEnum;
import com.xh.hongaicodegenerator.monitor.FluxContext;
import com.xh.hongaicodegenerator.monitor.MonitorContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.bsc.langgraph4j.action.AsyncNodeAction;
import org.bsc.langgraph4j.prebuilt.MessagesState;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.HashMap;
import java.util.Map;

import static org.bsc.langgraph4j.action.AsyncNodeAction.node_async;

/**
 * 代码初始化工作节点
 */
@Slf4j
public class CodeInitiatorNode {

    // 模板路径映射
    private static final Map<TemplateTypeEnum, String> TEMPLATE_PATH_MAP = new HashMap<>();
    static {
        TEMPLATE_PATH_MAP.put(TemplateTypeEnum.ENTERPRISE_WEBSITE, "tmp/code_template/enterprise_website_template");
        TEMPLATE_PATH_MAP.put(TemplateTypeEnum.ONLINE_STORE, "tmp/code_template/online_store_template");
        TEMPLATE_PATH_MAP.put(TemplateTypeEnum.WORK_SHOWING, "tmp/code_template/work_showing_template");
        TEMPLATE_PATH_MAP.put(TemplateTypeEnum.BLOG, "tmp/code_template/blog_template");
    }

    public static AsyncNodeAction<MessagesState<String>> create() {
        return node_async(state -> {
            WorkflowContext context = WorkflowContext.getContext(state);
            String generatedCodeDir=context.getGeneratedCodeDir();
            TemplateTypeEnum templateType=context.getTemplateTypeEnum();
            if (templateType != TemplateTypeEnum.WITHOUT_TEMPLATE){
                initiateCodeFromTemplate(context, templateType,generatedCodeDir);
            }
            // 更新状态
            context.setCurrentStep("初始化代码");
            Integer stepCount = context.getStepCount()+1;
            context.setStepCount(stepCount);
            FluxContext flux= MonitorContextHolder.getFlux();
            flux.getSink().next(String.format("\n\n第 %s 步 %s 执行完成\n\n",stepCount,"初始化代码"));
            return WorkflowContext.saveContext(context);
        });
    }

    private static void initiateCodeFromTemplate(WorkflowContext context, TemplateTypeEnum templateType, String generatedCodeDir) {
        // 获取模板路径
        String templatePath = TEMPLATE_PATH_MAP.get(templateType);
        if (templatePath == null) {
            log.error("未找到模板类型 {} 对应的模板路径", templateType);
            return;
        }

        // 创建生成代码目录
        File generatedDir = new File(generatedCodeDir);
        if (!generatedDir.exists()) {
            generatedDir.mkdirs();
        }

        // 复制模板文件到生成目录
        try {
            copyDirectory(templatePath, generatedCodeDir);
            log.info("模板文件复制完成，从 {} 到 {}", templatePath, generatedCodeDir);
            
            // 读取生成目录下的代码文件
//            String codeContent = CodeFileReaderTool.readAndConcatenateCodeFiles(generatedCodeDir);
            
            // 保存到上下文
            context.setInitiatedCode(true);
            
            log.info("代码初始化完成");
        } catch (Exception e) {
            log.error("复制模板文件或读取代码时发生错误", e);
        }
    }

    /**
     * 复制目录及其内容
     *
     * @param sourcePath 源目录路径
     * @param targetPath 目标目录路径
     * @throws Exception 复制过程中可能发生的异常
     */
    private static void copyDirectory(String sourcePath, String targetPath) throws Exception {
        Path sourceDir = Paths.get(sourcePath);
        Path targetDir = Paths.get(targetPath);
        
        Files.walk(sourceDir)
            .forEach(source -> {
                try {
                    Path target = targetDir.resolve(sourceDir.relativize(source));
                    Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
                } catch (Exception e) {
                    throw new RuntimeException("复制文件失败: " + source, e);
                }
            });
    }
}